import { ConfigModuleOptions } from '@nestjs/config';
import * as path from 'path';
import * as fs from 'fs';
import { EnvironmentVariables, AppConfig } from '@/common/config.interface';

/**
 * 根据环境变量加载对应的 JSON 配置文件
 */
export function getEnvConfig(): ConfigModuleOptions {
    const nodeEnv = process.env.NODE_ENV || 'development';

    // 环境文件映射
    const envFileMap: Record<string, string> = {
        development: 'config/env.local.json',
        production: 'config/env.prod.json',
        test: 'config/env.test.json',
        staging: 'config/env.staging.json',
    };

    const envFile = envFileMap[nodeEnv] || 'config/env.local.json';
    const envPath = path.resolve(process.cwd(), envFile);

    // 检查环境文件是否存在
    if (!fs.existsSync(envPath)) {
        process.stderr.write(`⚠️  环境配置文件 ${envFile} 不存在，使用默认配置\n`);
        return {
            isGlobal: true,
            cache: true,
            load: [() => getDefaultConfig()],
        };
    }

    // 使用 process.stdout 输出环境信息（在 log4js 配置之前）
    process.stdout.write(`📄 加载环境配置: ${envFile}\n`);

    return {
        isGlobal: true,
        cache: true,
        load: [
            () => {
                try {
                    const configContent = fs.readFileSync(envPath, 'utf8');
                    const config = JSON.parse(configContent) as EnvironmentVariables;

                    // 将配置转换为环境变量格式
                    const envVars: Record<string, string> = {};
                    Object.entries(config).forEach(([key, value]) => {
                        envVars[key] = String(value);
                    });

                    return envVars;
                } catch (error) {
                    process.stderr.write(`❌ 解析环境配置文件失败: ${error}\n`);
                    return getDefaultConfig();
                }
            },
        ],
        validationOptions: {
            allowUnknown: true,
            abortEarly: false,
        },
    };
}

/**
 * 获取默认配置
 */
function getDefaultConfig(): Record<string, string> {
    return {
        NODE_ENV: 'development',
        APP_PORT: '3000',
        DB_HOST: 'localhost',
        DB_PORT: '3306',
        DB_USERNAME: 'root',
        DB_PASSWORD: 'password',
        DB_DATABASE: 'nest_demo',
        DB_SYNCHRONIZE: 'false',
        DB_LOGGING: 'false',
        REDIS_HOST: 'localhost',
        REDIS_PORT: '6379',
        REDIS_PASSWORD: '',
        REDIS_DB: '0',
        REDIS_MAX_RETRIES: '3',
        JWT_SECRET: 'JWT_SECRET',
        JWT_EXPIRES_IN: '24h',
        LOG_LEVEL: 'info',
        DB_LOG_LEVEL: 'warn',
        CACHE_LOG_LEVEL: 'info',
        LOG_FORMAT: 'json',
        ENABLE_SWAGGER: 'false',
        ENABLE_DEBUG: 'false',
    };
}

/**
 * 环境变量验证配置
 */
export const envValidationSchema = {
    NODE_ENV: {
        required: true,
        enum: ['development', 'production', 'test', 'staging'],
        default: 'development',
    },
    APP_PORT: {
        required: false,
        type: 'number',
        default: 3000,
    },
    DB_HOST: {
        required: true,
        default: 'localhost',
    },
    DB_PORT: {
        required: false,
        type: 'number',
        default: 3306,
    },
    DB_USERNAME: {
        required: true,
        default: 'root',
    },
    DB_PASSWORD: {
        required: true,
        default: 'password',
    },
    DB_DATABASE: {
        required: true,
        default: 'nest_demo',
    },
    REDIS_HOST: {
        required: true,
        default: 'localhost',
    },
    REDIS_PORT: {
        required: false,
        type: 'number',
        default: 6379,
    },
    JWT_SECRET: {
        required: true,
        minLength: 16,
    },
    JWT_EXPIRES_IN: {
        required: false,
        default: '24h',
    },
    LOG_LEVEL: {
        required: false,
        enum: ['error', 'warn', 'info', 'debug'],
        default: 'info',
    },
};

/**
 * 获取当前环境信息
 */
export function getEnvironmentInfo(): AppConfig {
    const nodeEnv = process.env.NODE_ENV || 'development';
    const appPort = parseInt(process.env.APP_PORT || '3000', 10);
    const dbHost = process.env.DB_HOST || 'localhost';
    const redisHost = process.env.REDIS_HOST || 'localhost';

    return {
        nodeEnv,
        port: appPort,
        database: {
            host: dbHost,
            port: parseInt(process.env.DB_PORT || '3306', 10),
            database: process.env.DB_DATABASE || 'nest_demo',
            username: process.env.DB_USERNAME || 'root',
            password: process.env.DB_PASSWORD || 'password',
            synchronize: process.env.DB_SYNCHRONIZE === 'true',
            logging: process.env.DB_LOGGING === 'true',
            dropSchema: process.env.DB_DROP_SCHEMA === 'true',
        },
        redis: {
            host: redisHost,
            port: parseInt(process.env.REDIS_PORT || '6379', 10),
            password: process.env.REDIS_PASSWORD || '',
            db: parseInt(process.env.REDIS_DB || '0', 10),
            maxRetries: parseInt(process.env.REDIS_MAX_RETRIES || '3', 10),
        },
        jwt: {
            secret: process.env.JWT_SECRET || 'EHvvrvZ639twaCePmjVUBwHCdhJY5mr8',
            expiresIn: process.env.JWT_EXPIRES_IN || '24h',
        },
        logging: {
            level: process.env.LOG_LEVEL || 'info',
            dbLogLevel: process.env.DB_LOG_LEVEL || 'warn',
            cacheLogLevel: process.env.CACHE_LOG_LEVEL || 'info',
            format: process.env.LOG_FORMAT || 'json',
        },
        features: {
            swagger: process.env.ENABLE_SWAGGER === 'true',
            debug: process.env.ENABLE_DEBUG === 'true',
        },
    };
}
